#include <iostream>
#include <fstream>
#include <vector>
#include "txtpara.h"
#include "KDindex.h"
#include "speedup.h"
#include "directsampling.h"

using namespace std;

int main(int argc, char *argv[])
{
    /* direct sampling parameters */
    int NR_neighbor=24;//Maximum number of neighbors
    int NR_try=100; //Maximum number of search
    float tolerance=1;//tolerance of difference
    /**/
    int xsize,ysize,zsize;
    int G=1;
    int objsize;
    int unitsize=1;
    char* config=argv[1];
    NR_neighbor=getparaINT("NR_neighbor",config);
    tolerance=getparaDOUBLE("tolerance",config);
    diff_degree=getparaDOUBLE("diff_degree",config)*255;//Here we presume that the maximum continuous variable value is 255
    xsize=getparaINT("xsize",config);
    ysize=getparaINT("ysize",config);
    zsize=getparaINT("zsize",config);
    float *target=new float[xsize*ysize*zsize];
    for(int i=0;i<xsize*ysize*zsize;i++){
        target[i]=-1;
    }
    objsize=1<<G;
    unitsize=getparaINT("unitsize",config);
    vector<coord> sample;
    //Step 1.  Generate the coarser grid
    srand(clock());
    int N_sample=0;
    vector <int> ids;
    ids.clear();
    for(int z=0;z<zsize;z+=objsize){
        for(int y=0;y<ysize;y+=objsize){
            for(int x=0;x<xsize;x+=objsize){
                coord s;
                s.x=x;s.y=y;s.z=z;
                sample.push_back(s);
                ids.push_back(N_sample);
                N_sample++;
            }
        }
    }
    //Step 2.  The simulation on the coarsest grid
    //Generate Random path;
    for(int s_no=0;s_no<N_sample;s_no++){
        int ranid=rand()%N_sample;
        int tmp=ids[s_no];
        ids[s_no]=ids[ranid];
        ids[ranid]=tmp;
    }
    Index <L2<float> > *R=createIndex();
    float *ti;
    int tilength, tiwidth,tiheight;
    int start_id=0;
    int level=0;
    load_ti_3D(&ti,argv[2],&tilength,&tiwidth,&tiheight);
    NR_try=int(getparaDOUBLE("Fraction",config)*tilength*tiwidth*tiheight);
    Simulation_cont(R, ti, NR_neighbor, NR_try, tolerance, sample, ids, target, N_sample, tilength, tiwidth, tiheight, unitsize, start_id, level,xsize,ysize,zsize);
    //Step 3   Finding border points and Generate random points around neighbors
    find_border_cont(start_id, G-level, sample, ids, target,xsize,ysize,zsize);
    start_id=ids.size();
    level++;
    for(int s_no=start_id;s_no<sample.size();s_no++){
        ids.push_back(s_no);
    }
    for(int s_no=start_id;s_no<sample.size();s_no++){
        //Generate Random path;
        int ranid=rand()%(sample.size()-start_id)+start_id;
        int tmp=ids[s_no];
        ids[s_no]=ids[ranid];
        ids[ranid]=tmp;
    }
    //Step 4   Generate simulation on the finest grid
    Simulation_cont(R, ti, NR_neighbor, NR_try, tolerance, sample, ids, target, sample.size()-start_id, tilength, tiwidth, tiheight, unitsize, start_id, level,xsize,ysize,zsize);
    smooth_all_cont(0, target, xsize,ysize,zsize);
    for(int y=0;y<ysize;y+=1){
        for(int x=0;x<xsize;x+=1){
            if (-1==target[x+y*xsize]){
                cout<<"*"<<" ";
            }else{
                cout<<target[x+y*xsize]<<" ";
            }
        }
        cout<<endl;
    }
    return 0;
}
